"""
SimpleAPI 文档生成模块
支持自动生成OpenAPI规范和提供Swagger UI/ReDoc界面
"""

import json
import os
import inspect
from typing import Dict, Any, Optional, List, Callable
from pathlib import Path


class OpenAPIGenerator:
    """OpenAPI规范生成器"""
    
    def __init__(self, title: str = "SimpleAPI", version: str = "1.0.0", description: str = ""):
        self.title = title
        self.version = version
        self.description = description
        self.paths = {}
        self.components = {
            "schemas": {},
            "responses": {},
            "parameters": {},
            "examples": {},
            "requestBodies": {},
            "headers": {},
            "securitySchemes": {},
            "links": {},
            "callbacks": {}
        }
        self.tags = []
        
    def add_path(self, path: str, method: str, operation: Dict[str, Any]):
        """添加API路径"""
        if path not in self.paths:
            self.paths[path] = {}
        
        self.paths[path][method.lower()] = operation
    
    def add_route_from_function(self, path: str, method: str, func: Callable, 
                               summary: str = None, description: str = None,
                               tags: List[str] = None):
        """从函数自动生成路由文档"""
        operation = {
            "summary": summary or func.__name__.replace('_', ' ').title(),
            "description": description or func.__doc__ or "",
            "operationId": f"{method.lower()}_{func.__name__}",
            "tags": tags or [],
            "responses": {
                "200": {
                    "description": "Successful response",
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object"
                            }
                        }
                    }
                }
            }
        }
        
        # 分析函数签名
        sig = inspect.signature(func)
        parameters = []
        
        for param_name, param in sig.parameters.items():
            if param_name in ['request', 'self']:
                continue
                
            param_info = {
                "name": param_name,
                "in": "query",  # 默认为查询参数
                "required": param.default == inspect.Parameter.empty,
                "schema": {
                    "type": self._get_python_type_to_openapi(param.annotation)
                }
            }
            
            # 如果参数在路径中，设置为路径参数
            if f"{{{param_name}}}" in path:
                param_info["in"] = "path"
                param_info["required"] = True
            
            parameters.append(param_info)
        
        if parameters:
            operation["parameters"] = parameters
        
        self.add_path(path, method, operation)
    
    def _get_python_type_to_openapi(self, python_type) -> str:
        """将Python类型转换为OpenAPI类型"""
        type_mapping = {
            int: "integer",
            float: "number", 
            str: "string",
            bool: "boolean",
            list: "array",
            dict: "object"
        }
        
        if python_type in type_mapping:
            return type_mapping[python_type]
        elif hasattr(python_type, '__origin__'):
            # 处理泛型类型如List[str]
            if python_type.__origin__ == list:
                return "array"
            elif python_type.__origin__ == dict:
                return "object"
        
        return "string"  # 默认类型
    
    def generate_spec(self) -> Dict[str, Any]:
        """生成完整的OpenAPI规范"""
        spec = {
            "openapi": "3.0.3",
            "info": {
                "title": self.title,
                "version": self.version,
                "description": self.description
            },
            "paths": self.paths
        }
        
        if self.components["schemas"] or any(self.components.values()):
            spec["components"] = {k: v for k, v in self.components.items() if v}
        
        if self.tags:
            spec["tags"] = self.tags
            
        return spec
    
    def to_json(self, indent: int = 2) -> str:
        """转换为JSON字符串"""
        return json.dumps(self.generate_spec(), indent=indent, ensure_ascii=False)


class StaticFileHandler:
    """静态文件处理器"""
    
    def __init__(self, static_dir: str = None):
        if static_dir is None:
            # 默认使用包内的static目录
            current_dir = Path(__file__).parent
            static_dir = current_dir / "static"
        
        self.static_dir = Path(static_dir)
    
    def get_file_content(self, file_path: str) -> Optional[bytes]:
        """获取静态文件内容"""
        try:
            full_path = self.static_dir / file_path
            if full_path.exists() and full_path.is_file():
                with open(full_path, 'rb') as f:
                    return f.read()
        except Exception as e:
            print(f"Error reading static file {file_path}: {e}")
        return None
    
    def get_content_type(self, file_path: str) -> str:
        """根据文件扩展名获取Content-Type"""
        ext = Path(file_path).suffix.lower()
        content_types = {
            '.html': 'text/html; charset=utf-8',
            '.css': 'text/css; charset=utf-8', 
            '.js': 'application/javascript; charset=utf-8',
            '.json': 'application/json; charset=utf-8',
            '.png': 'image/png',
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.gif': 'image/gif',
            '.svg': 'image/svg+xml',
            '.ico': 'image/x-icon'
        }
        return content_types.get(ext, 'application/octet-stream')


class DocsIntegration:
    """文档集成类，用于集成到SimpleAPI框架中"""
    
    def __init__(self, app, title: str = "SimpleAPI", version: str = "1.0.0", 
                 description: str = "", docs_url: str = "/docs", 
                 redoc_url: str = "/redoc", openapi_url: str = "/openapi.json"):
        self.app = app
        self.openapi_generator = OpenAPIGenerator(title, version, description)
        self.static_handler = StaticFileHandler()
        self.docs_url = docs_url
        self.redoc_url = redoc_url
        self.openapi_url = openapi_url
        
        # 注册文档路由
        self._register_docs_routes()
    
    def _register_docs_routes(self):
        """注册文档相关路由"""
        
        # OpenAPI JSON规范
        def openapi_json_handler(request):
            return self.openapi_generator.to_json()
        
        # 注册OpenAPI JSON路由
        self.app.app.get(self.openapi_url)(openapi_json_handler)
        
        # Swagger UI
        def swagger_ui_handler(request):
            content = self.static_handler.get_file_content("swagger-ui/index.html")
            if content:
                return content.decode('utf-8')
            return "Swagger UI not available"
        
        self.app.app.get(self.docs_url)(swagger_ui_handler)
        
        # Swagger UI 静态资源
        def swagger_css_handler(request):
            content = self.static_handler.get_file_content("swagger-ui/swagger-ui.css")
            if content:
                return content
            return "File not found", 404
            
        def swagger_js_handler(request):
            content = self.static_handler.get_file_content("swagger-ui/swagger-ui-bundle.js")
            if content:
                return content
            return "File not found", 404
            
        def swagger_preset_handler(request):
            content = self.static_handler.get_file_content("swagger-ui/swagger-ui-standalone-preset.js")
            if content:
                return content
            return "File not found", 404
        
        self.app.app.get(f"{self.docs_url}/swagger-ui.css")(swagger_css_handler)
        self.app.app.get(f"{self.docs_url}/swagger-ui-bundle.js")(swagger_js_handler)
        self.app.app.get(f"{self.docs_url}/swagger-ui-standalone-preset.js")(swagger_preset_handler)
        
        # ReDoc
        def redoc_handler(request):
            content = self.static_handler.get_file_content("redoc/index.html")
            if content:
                return content.decode('utf-8')
            return "ReDoc not available"
        
        self.app.app.get(self.redoc_url)(redoc_handler)
        
        # ReDoc 静态资源
        def redoc_js_handler(request):
            content = self.static_handler.get_file_content("redoc/redoc.standalone.js")
            if content:
                return content
            return "File not found", 404
        
        self.app.app.get(f"{self.redoc_url}/redoc.standalone.js")(redoc_js_handler)
    
    def add_route_docs(self, path: str, method: str, func: Callable,
                      summary: str = None, description: str = None,
                      tags: List[str] = None):
        """为路由添加文档"""
        self.openapi_generator.add_route_from_function(
            path, method, func, summary, description, tags
        )
    
    def update_info(self, title: str = None, version: str = None, description: str = None):
        """更新API信息"""
        if title:
            self.openapi_generator.title = title
        if version:
            self.openapi_generator.version = version
        if description:
            self.openapi_generator.description = description 